package com.yonyou.pmclouds.plan.utils;

import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.ref.itf.TreeVODependencyitf;
import com.yonyou.pmclouds.basecom.util.TreeVOCycleCheckUtil;
import com.yonyou.pmclouds.plan.entity.ScheduleItemVO;
import com.yonyou.pmclouds.plan.entity.ScheduleVO;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @Author chulf
 * @Date 2020/3/16
 * @Description  这里对时间格式及 循环引用 进行校验
 *               1.所有孩子节点开始时间不得早于父节点时间
 *               2.所有节点开始时间不得早于依赖的结束时间
 **/
public class ScheduleDataCheckUtil {

    private static void checkItemDate(ScheduleItemVO itemVO, Map<String, TreeVODependencyitf> itemVOS) throws BusinessException {

        Date startDate = itemVO.getPlanStartDate();

        ScheduleItemVO[] children = itemVO.getChildren();
        if(!ArrayUtils.isEmpty(children)){
            //校验所有孩子时间不能早于父亲时间
            for (ScheduleItemVO child : children) {
                Date childStartDate = child.getPlanStartDate();
                if(childStartDate.getTime() < startDate.getTime()) throw new BusinessException("孩子节点"+child.getCode()+"的时间不得早于父亲"+itemVO.getCode()+"的时间");
                checkItemDate(child,itemVOS);
            }
        }
        String dependPlan = itemVO.getDependPlan();
        if(!StringUtils.isEmpty(dependPlan)){
            //校验当前节点时间不能早于依赖的时间
            ScheduleItemVO scheduleItemVO = (ScheduleItemVO) itemVOS.get(dependPlan);
            Date dependStartDate = scheduleItemVO.getPlanStartDate();
            if(startDate.getTime() <= dependStartDate.getTime()) throw new BusinessException("当前节点"+itemVO.getCode()+"的时间不得早于依赖节点"+scheduleItemVO.getCode()+"的时间");
        }
    }

    public static void checkData(ScheduleVO scheduleVO) throws BusinessException {
        ScheduleItemVO[] scheduleItemVOS = scheduleVO.getScheduleItemVOS();

        HashMap<String, TreeVODependencyitf> pk2ScheduleItemVO = new HashMap<>();

        //填充 所有的 pk 2 scheduleItemVO 的映射
        for (ScheduleItemVO scheduleItemVO : scheduleItemVOS) {
            setPk2ScheduleItemVOMap(scheduleItemVO,pk2ScheduleItemVO);
        }

        TreeVOCycleCheckUtil treeVOCycleCheckUtil = new TreeVOCycleCheckUtil(pk2ScheduleItemVO);

        //校验是否将父类或子类设置为前置依赖
        Collection<TreeVODependencyitf> datas = pk2ScheduleItemVO.values();

        for (TreeVODependencyitf data : datas) {
            if(treeVOCycleCheckUtil.cehckIsParent(data)) throw new BusinessException("当前节点"+data.findCode()+"不能将父类设置为前置依赖");
            if(treeVOCycleCheckUtil.cehckIsChild(data)) throw new BusinessException("当前节点"+data.findCode()+"不能将子类设置为前置依赖");
        }


        //校验所有的时间 及是否有环 及父类和子类
        for (ScheduleItemVO scheduleItemVO : scheduleItemVOS) {
            Set<String> cycleRelation = treeVOCycleCheckUtil.getCycleRelation(scheduleItemVO);
            if (cycleRelation != null && cycleRelation.size() > 0) {

                StringBuffer relationMsg = new StringBuffer();
                for (String pk : cycleRelation) {
                    relationMsg.append(pk2ScheduleItemVO.get(pk).findCode());
                    relationMsg.append("->");
                }
                String finalMsg = relationMsg.substring(0, relationMsg.length() - 2);//去掉最后的箭头


                throw new BusinessException("当前节点"+scheduleItemVO.getCode()+"出现环路:"+finalMsg);
            }
            checkItemDate(scheduleItemVO,pk2ScheduleItemVO);
        }
    }
    private static void setPk2ScheduleItemVOMap(ScheduleItemVO treeVO, Map<String, TreeVODependencyitf> map){

        map.put(treeVO.getPkScheduleItem(),treeVO);
        ScheduleItemVO[] children = treeVO.getChildren();
        if(!ArrayUtils.isEmpty(children)){
            for (ScheduleItemVO child : children) {
                setPk2ScheduleItemVOMap(child,map);
            }
        }
    }
}
